home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Cream of the Crop 26
/
Cream of the Crop 26.iso
/
doom
/
quake.zip
/
KASCAM17.ZIP
/
SOURCE
/
KASCAM.QC
< prev
next >
Wrap
Text File
|
1997-05-25
|
25KB
|
1,096 lines
//Kasuha's DeathMatch Camera QC patch version 1.5
/////////////////////////////////////////////////////////////////////////////
// KasCam definitions
/////////////////////////////////////////////////////////////////////////////
// KasCam constants
float CAM_IDLE = 0; // Camera idle, nobody to look at
float CAM_FIXED = 1; // Fixed-position camera
float CAM_FLYBY = 2; // Fly-by camera
float CAM_FOLLOW = 3; // Camera following a player
float CAM_HAND = 4; // Hand-targeted camera
float CAM_FREE = 5; // Flying hand-targeted camera
float CAM_NOCLIP = 6; // No-clipping flying blabla
float CAM_DEATH = 7; // Death camera
// KasCam variables
entity CamClient; // Camera client
entity CamTargEnt; // Targeted entity
vector CamPos; // Current expected camera position
vector CamTarget; // Current expected targeted point
vector CamNexTrg; // Next target for idle mode
vector CamAngV; // Angle speed
float CamDist; // Max distance for flyby mode
float CamMsgs; // "take" messages ON/OFF
float CamState; // Camera state
float CamLastFrameTime; // For time measure
float CamNextThink; // Delay measure
float CamDrop; // When drop from current mode
float CamForceTarget; // How long to keep current target / idle mode
entity CamLastTarg; // Previous target
/////////////////////////////////////////////////////////////////////////////
// end of KasCam definitions
/////////////////////////////////////////////////////////////////////////////
// KasCam functions
entity(entity ent) CamCycle =
{
ent = find(ent,classname,"player");
return ent;
};
void(entity ent) CamVectors =
{
makevectors(ent.v_angle);
};
void(entity client, string s1, string s2, string s3, string s4, string s5, string s6) camcenterprint = #73;
void(entity ent, string tit) CamReport =
{
local string s2,s3;
if (ent.frags < 1) {
s2 = "no";
} else {
s2 = ftos(ent.frags);
}
if (ent.frags != 1) {
s3 = " frags";
} else {
s3 = " frag";
}
camcenterprint(self,tit,"\n\n\n",ent.netname," - ",s2,s3);
};
// There is NO square root ?!
float(float num) CamSqrt =
{
local float apr;
if (num < 0.001)
return 0;
if (num>1) {
apr = num;
} else {
apr = 1;
}
do {
apr = (num + (apr * apr)) / (2 * apr);
} while (fabs((apr * apr) - num) > (num * 0.001));
return apr;
};
// Angle normalization
float(float a) CamReAngle =
{
while (a>180) a = a - 360;
while (a<-180) a = a + 360;
return a;
};
// Visibility test
float(vector vec) CamVisible =
{
traceline(self.origin,vec,TRUE,self);
return ((trace_fraction == 1) && !((trace_inopen && trace_inwater)));
};
entity() CamShoot =
{
local entity ent,entx;
local vector vec;
local float d1,dx;
makevectors(self.v_angle);
entx = world;
ent = CamCycle(world);
dx = 0;
while (ent != world) {
if (ent.deadflag == DEAD_NO) {
vec = ent.origin - self.origin;
vec = normalize(vec);
d1 = (v_forward_x * vec_x) + (v_forward_y * vec_y) + (v_forward_z * vec_z);
if (d1 > dx) {
if (CamVisible(ent.origin)) {
entx = ent;
dx = d1;
}
}
}
ent = CamCycle(ent);
}
return entx;
};
float(float d, float a) CamHurry =
{
local float dd,t,tt;
if (d<0) a = 0 - a;
t = time - CamLastFrameTime;
tt = CamSqrt(d / a);
if (t > tt) {
return d;
} else {
return (a * t * ((2 * tt) - t));
}
};
// Watch out! This is probably the most sophisticated routine ;-)
// I spent 5 hours developing the algorithm
// If you understand how it works in 3 minutes you're a guru :-)))
vector(float s, float v, float a) CamSmooth =
{
local float dt,t1,t2,v2,as,sv2,b;
local vector vec;
s = CamReAngle(s);
v2 = v / 2;
as = a * s;
sv2 = v2 * v2;
dt = time - CamLastFrameTime;
if (fabs(as) < sv2) {
b = v > 0;
} else {
b = s > 0;
}
if (b) {
t2 = CamSqrt((sv2 + as) / 2) / a;
a = 0 - a;
} else {
t2 = CamSqrt((sv2 - as) / 2) / a;
}
t1 = t2 - (v2 / a);
if (t1 > dt) {
s = (a * dt + v) * dt + s;
v = a * dt * 2 + v;
} else {
s = (a * t1 + v) * t1 + s;
v = a * t1 * 2 + v;
t1 = dt - t1;
if (t1 < t2) {
s = (v - (a * t1)) * t1 + s;
v = v - (a * t1 * 2);
} else {
s = 0;
v = 0;
}
}
vec_x = s;
vec_y = v;
return vec;
};
float(entity ent) CamVisibleEnt =
{
local vector vec;
// Three points: origin, bottom and eyes
if (CamVisible(ent.origin)) return TRUE;
vec = ent.origin;
vec_z = ent.absmin_z;
if (CamVisible(vec)) return TRUE;
vec_z = ent.absmax_z - 8;
return CamVisible(vec);
};
float(vector vec) TryFlybyVector =
{
local vector orig,vec1;
local float vl;
vec1 = normalize(vec);
vec = 700 * vec1;
orig = CamTargEnt.origin;
orig_z = CamTargEnt.absmax_z - 8;
traceline(orig,orig+vec,TRUE,self);
if (trace_inopen && trace_inwater) return 1111;
trace_endpos = trace_endpos - vec1;
vl = vlen(CamTargEnt.origin - trace_endpos);
if (vl<50) return 1111;
if (pointcontents(trace_endpos) == CONTENT_SOLID) return 1111;
return fabs(333 - vl);
};
// Angle moving;
float(float src,float dst,float spd) CamAngMove =
{
local float d,dd;
d = dst - src;
while (d>180) d = d - 360;
while (d<-180) d = d + 360;
if (fabs(d)>1.5) {
dd = CamHurry(d,spd);
} else {
dd = 0;
}
return src + dd;
};
// Move camera towards ideal position (or just skip there)
void(float speedv, float speeda) CamUpdatePos =
{
local vector vec, v1;
local float vl;
// Check destination visibility
traceline(self.origin,CamPos,TRUE,self);
if (trace_fraction != 1) {
speedv = 0;
speeda = 0;
}
// Rotate the camera towards the target
// and move it towards the ideal position
if (speedv == 0) {
setorigin(self,CamPos);
} else {
vec = CamPos - self.origin;
vl = vlen(vec);
vec = normalize(vec);
vl = CamHurry(vl,speedv);
vec = vl * vec;
setorigin(self,self.origin + vec);
}
self.fixangle = TRUE;
self.movetype = MOVETYPE_NONE;
if (CamState != CAM_DEATH) {
vec = vectoangles(CamTarget - CamPos);
} else {
vec = vectoangles(CamTarget - CamClient.origin);
}
vec_z = 0;
vec_x = CamReAngle(360 - vec_x);
vec_y = CamReAngle(vec_y);
if (vec_x > 70) {
vec_x = 70;
} else {
if (vec_x < -70) vec_x = -70;
}
if (speeda == 0) {
self.angles = vec;
CamAngV = '0 0 0';
} else {
v1 = CamSmooth(self.angles_x - vec_x,CamAngV_x,speeda);
CamAngV_x = v1_y;
self.angles_x = vec_x + v1_x;
v1 = CamSmooth(self.angles_y - vec_y,CamAngV_y,speeda);
CamAngV_y = v1_y;
self.angles_y = vec_y + v1_x;
self.angles_x = CamReAngle(self.angles_x);
self.angles_y = CamReAngle(self.angles_y);
}
self.v_angle = self.angles;
};
void() CamSetAuto =
{
CamPos = self.origin;
makevectors(self.v_angle);
CamTarget = self.origin+v_forward;
CamUpdatePos(0,0);
};
void() CamGoIdle =
{
CamSetAuto();
CamState = CAM_IDLE;
CamNextThink = time;
CamDrop = time;
CamNexTrg = CamTarget;
CamTargEnt = CamClient;
};
void() CamGoDeath =
{
CamAngV = '0 0 0';
CamPos = CamClient.origin;
CamState = CAM_DEATH;
CamNextThink = time + 1;
CamLastTarg = world;
};
// FlyBy mode initialization
// Targeted player is in CamTargEnt
void(entity newtarg) CamInitFlybyMode =
{
local float f, max;
local vector vec, vec2;
local entity ent;
// Keep camera at this point some time...
CamNextThink = time + 0.4;
// Report selected player
if (CamTargEnt != newtarg) {
CamTargEnt = newtarg;
if (CamLastTarg != CamTargEnt) {
if (CamMsgs) {
CamReport(CamTargEnt,"Now taking");
}
CamLastTarg = newtarg;
}
}
vec = CamTargEnt.angles;
vec_x = 0;
makevectors (vec);
v_forward = 3 * v_forward;
max = 1000;
f = TryFlybyVector(v_forward + v_up + v_right);
if (f<max) {
max = f;
vec = trace_endpos;
}
f = TryFlybyVector(v_forward + v_up - v_right);
if (f<max) {
max = f;
vec = trace_endpos;
}
f = TryFlybyVector(v_forward + v_right);
if (f<max) {
max = f;
vec = trace_endpos;
}
f = TryFlybyVector(v_forward - v_right);
if (f<max) {
max = f;
vec = trace_endpos;
}
f = TryFlybyVector(v_forward + v_up);
if (f<max) {
max = f;
vec = trace_endpos;
}
f = TryFlybyVector(v_up - v_forward);
if (f<max) {
max = f;
vec = trace_endpos;
}
f = TryFlybyVector(v_up + v_right - v_forward);
if (f<max) {
max = f;
vec = trace_endpos;
}
f = TryFlybyVector(v_up - v_right - v_forward);
if (f<max) {
max = f;
vec = trace_endpos;
}
if (max >= 1000) {
CamGoIdle();
CamNextThink = time + 2;
return;
}
CamTarget = CamTargEnt.origin;
CamPos = vec;
CamState = CAM_FLYBY;
CamDist = 1.5 * vlen(CamPos - CamTarget);
if (CamDist < 500) CamDist = 500;
CamUpdatePos(0,0);
};
vector() GetFollowCam =
{
local vector vec, vec2;
CamVectors(CamTargEnt);
vec = CamTargEnt.origin + (CamTargEnt.maxs_z + 4) * v_up;
traceline(CamTargEnt.origin,vec,FALSE,self);
vec = trace_endpos - normalize(vec);
vec2 = -100 * v_forward;
traceline(vec,vec+vec2,TRUE,self);
vec2 = trace_endpos - normalize(vec2);
if (CamVisible(vec2)) {
return vec2;
} else {
return vec;
}
};
vector() GetFollowTrg =
{
local vector vec;
if (CamTargEnt.deadflag == DEAD_NO) {
CamVectors(CamTargEnt);
vec = CamTargEnt.origin + 2048 * v_forward;
} else {
vec = CamTargEnt.origin;
}
return vec;
};
// Move the camera to the point it is looking at
void() CamHandJump =
{
makevectors(self.v_angle);
traceline(self.origin,self.origin+2000*v_forward,TRUE,self);
CamPos=trace_endpos - normalize(trace_endpos-self.origin);
CamTarget = self.origin;
CamUpdatePos(0,0);
};
// find n-th saved position
entity(float n) CamGetPos =
{
local entity ent;
ent = find(world,classname,"CamSavedPos");
while((n>0) && (ent!=world)) {
ent = find(ent,classname,"CamSavedPos");
n = n - 1;
}
return ent;
};
// save actual position and angles
void(float n) CamSavePos =
{
local entity ent;
ent = CamGetPos(n);
if (ent!=world) {
ent.angles = self.angles;
ent.v_angle = self.v_angle;
setorigin(ent,self.origin);
}
};
// save actual position and angles
void(float n) CamLoadPos =
{
local entity ent;
if ((CamState == CAM_HAND) || (CamState == CAM_FREE) || (CamState == CAM_NOCLIP)) {
ent = CamGetPos(n);
if (ent!=world) {
self.fixangle = TRUE;
self.angles = ent.angles;
self.v_angle = ent.v_angle;
setorigin(self,ent.origin);
}
}
};
// Impulse handling
void() CamImpulses =
{
local float c;
local entity ent;
// Choose target automatically
if (self.impulse == 100) {
CamGoIdle();
// Choose target manually
} else if ((self.impulse > 100) && (self.impulse <150)) {
c = self.impulse - 100;
ent = world;
do {
ent = CamCycle(ent);
c = c - 1;
} while ((c>0) && (ent != world));
if (ent != world) {
if (ent.deadflag == DEAD_NO) {
CamInitFlybyMode(ent);
CamForceTarget = time + 10;
CamDrop = time + 60;
}
}
// Save position
} else if((self.impulse>=180) && (self.impulse<=189)) {
c = self.impulse - 180;
CamSavePos (c);
// Load position
} else if((self.impulse>=190) && (self.impulse<=199)) {
c = self.impulse - 190;
CamLoadPos (c);
// Force FLYBY
} else if (self.impulse == 200) {
if (CamTargEnt != self) {
CamInitFlybyMode(CamTargEnt);
} else {
ent = CamShoot();
if (ent != world) {
CamInitFlybyMode(ent);
CamForceTarget = time + 10;
CamDrop = time + 60;
}
}
// Force FOLLOW
} else if (self.impulse == 201) {
if (CamTargEnt != self) {
CamState = CAM_FOLLOW;
} else {
ent = CamShoot();
if (ent != world) {
CamTargEnt = ent;
if (CamTargEnt != CamLastTarg) {
CamLastTarg = CamTargEnt;
if (CamMsgs) {
CamReport(CamTargEnt,"Now Taking");
}
}
CamState = CAM_FOLLOW;
CamDrop = time + 60;
CamAngV = '0 0 0';
CamForceTarget = time + 10;
}
}
// Force HAND
} else if (self.impulse == 202) {
if ((CamState != CAM_FLYBY) && (CamState != CAM_FIXED)) CamHandJump();
CamState = CAM_HAND;
self.movetype = MOVETYPE_NONE;
CamTargEnt = CamClient;
CamLastTarg = world;
// Force FREE (FLY)
} else if (self.impulse == 203) {
CamState = CAM_FREE;
self.movetype = MOVETYPE_FLY;
CamTargEnt = CamClient;
CamLastTarg = world;
// Force NOCLIP
} else if (self.impulse == 204) {
CamState = CAM_NOCLIP;
CamTargEnt = CamClient;
CamLastTarg = world;
self.movetype = MOVETYPE_NOCLIP;
// Force FIXED
} else if (self.impulse == 205) {
if ((CamState == CAM_FLYBY) || (CamState == CAM_HAND)) {
CamSetAuto();
CamState = CAM_FIXED;
CamTargEnt = CamClient;
CamLastTarg = world;
CamDrop = time + 100000;
CamNextThink = time + 3;
}
// Messages ON/OFF
} else if (self.impulse == 210) {
CamMsgs = !CamMsgs;
// Report position
} else if (self.impulse == 211) {
bprint("Current camera position: ");
bprint(vtos(self.origin));
bprint("\n");
}
self.impulse = 0;
};
// Update camera state according to current target
void() CamUpdValues =
{
local float it;
if ((CamTargEnt != CamClient) && (CamTargEnt.classname != "bodyque") && (CamTargEnt.health > 0)) {
// Mask out items which change view color
it = IT_INVISIBILITY | IT_INVULNERABILITY | IT_SUIT | IT_QUAD;
self.items = (CamTargEnt.items | it) - it;
self.health = CamTargEnt.health;
self.armorvalue = CamTargEnt.armorvalue;
self.ammo_shells = CamTargEnt.ammo_shells;
self.ammo_nails = CamTargEnt.ammo_nails;
self.ammo_rockets = CamTargEnt.ammo_rockets;
self.ammo_cells = CamTargEnt.ammo_cells;
self.weapon = CamTargEnt.weapon;
self.currentammo = CamTargEnt.currentammo;
} else {
self.items = 0;
self.health = 111;
self.armorvalue = 111;
self.ammo_shells = 1;
self.ammo_nails = 1;
self.ammo_rockets = 1;
self.ammo_cells = 1;
self.weapon = IT_AXE;
self.currentammo = 11;
}
};
// Overall health
float(entity ent) CamHealthVal =
{
local float alldmg;
// First evaluate max damage if infinite armor
alldmg = ent.health/(1-ent.armortype);
// Test for less armor
if (alldmg>(ent.health+ent.armorvalue)) {
alldmg = ent.health+ent.armorvalue;
}
// And return maximum damage entity can bear
return alldmg;
};
// IDLE mode think routine
void() CamIdleThink =
{
local entity ent,ent2;
local vector vec;
local float p1,p2;
// Prepare a sentinel
ent2 = self;
p2 = -1;
p1 = 5 * random();
// try to find some interesting target
if (p1 < 1) {
ent = CamCycle(world);
while (ent != world) {
// Dead or dying are not interesting at this point
if (ent.deadflag == DEAD_NO) {
p1 = CamHealthVal(ent);
if (ent2 == self) {
ent2 = ent;
p2 = p1;
} else {
if (p2<p1) {
ent2 = ent;
p2 = p1;
}
}
}
ent = CamCycle(ent);
}
} else if (p1 < 2) {
ent = CamCycle(world);
while (ent != world) {
// Dead or dying are not interesting at this point
if (ent.deadflag == DEAD_NO) {
p1 = ent.frags;
if (ent2 == self) {
ent2 = ent;
p2 = p1;
} else {
if (p2<p1) {
ent2 = ent;
p2 = p1;
}
}
}
ent = CamCycle(ent);
}
} else {
p2 = 0;
ent = CamCycle(world);
while (ent != world) {
if (ent.deadflag == DEAD_NO) p2 = p2 + 1;
ent = CamCycle(ent);
}
if (p2 > 0) {
p2 = p2 * random();
ent = world;
do {
do {
ent = CamCycle(ent);
} while (ent.deadflag != DEAD_NO);
p2 = p2 - 1;
} while (p2 > 0);
if (ent != world) ent2 = ent;
}
}
// If an interesting object found
if (ent2 != self) {
// Go to FlyBy mode
CamInitFlybyMode (ent2);
CamForceTarget = time + 10;
CamDrop = time + 60;
} else {
// Idle moves
CamTargEnt = CamClient;
traceline(CamPos,CamTarget,TRUE,self);
if (trace_fraction != 1) CamTarget = trace_endpos;
vec_x = 140 * random () - 70;
vec_y = 360 * random ();
vec_z = 0;
makevectors(vec);
vec = 2000 * v_forward;
vec = CamPos + vec;
traceline(CamPos, vec, TRUE, self);
if (trace_fraction != 1) vec = trace_endpos;
p1 = vlen(vec - CamPos);
p2 = vlen(CamTarget - CamPos);
if (p1 > p2) {
CamNexTrg = vec;
}
if (CamNextThink < time) {
CamNextThink = time + 3 + (2 * random());
CamTarget = CamNexTrg;
}
if (CamDrop < time) {
vec = CamPos + 0.97 * (CamTarget - CamPos);
traceline(self.origin,vec, TRUE, self);
if (trace_fraction == 1) {
CamPos = vec;
CamDrop = time + 8 + (5 * random());
}
}
}
};
// FLYBY mode thinking routine
void() CamFlyByThink =
{
local float p0,p1,grad;
local vector vec;
local entity ent;
// CamTarget is set to player
// Check if the player is not dead
if (CamTargEnt.deadflag != DEAD_NO) {
if (CamMsgs) CamReport(CamTargEnt,"R.I.P.");
CamGoDeath();
CamDrop = time + 5;
return;
}
// All other restrictions apply after some time
// Test player visibility
// If player not visible place another camera
p1 = vlen(CamPos - CamTargEnt.origin);
if ((CamVisibleEnt(CamTargEnt) && (CamDist > p1)) || (CamNextThink > time)) {
CamTarget = CamTargEnt.origin;
} else {
CamInitFlybyMode (CamTargEnt);
}
// Check for FOLLOW mode change
// Player has to be near
// And looking away
// And the destination point must be visible
p1 = vlen(CamTargEnt.origin - self.origin);
if (p1 < 170) {
// Player is near enough
// Now if it points away
grad = fabs(CamTargEnt.angles_y - self.angles_y);
if (grad > 180) grad = 360 - grad;
if (grad < 30) {
// Calculate following point
vec = GetFollowCam();
if (CamVisible(vec)) {
CamState = CAM_FOLLOW;
return;
}
}
}
p0 = 0;
p1 = 0;
if (CamForceTarget < time) {
ent = CamCycle(world);
while (ent != world) {
p0 = p0 + 1;
if (ent.deadflag == DEAD_NO) {
if (CamVisible(ent.origin)) {
p1 = p1 + 1;
}
}
ent = CamCycle(ent);
}
}
if (p0<4) {
p0 = 2;
} else if (p0<8) {
p0 = 3;
} else {
p0 = 4;
}
if (p1 > p0) {
CamTargEnt = CamClient;
CamLastTarg = world;
CamState = CAM_FIXED;
CamDrop = time + 15;
CamNextThink = time + 3;
}
if (CamDrop < time) {
CamGoIdle();
}
};
// FOLLOW mode thinking routine
void() CamFollowThink =
{
local entity ent;
local vector vec;
// Check player death
if (CamTargEnt.deadflag != DEAD_NO) {
if (CamMsgs) CamReport(CamTargEnt,"R.I.P.");
CamGoDeath();
CamDrop = time + 5;
return;
} else {
if (CamVisibleEnt(CamTargEnt)) {
CamPos = GetFollowCam();
CamTarget = GetFollowTrg();
if (pointcontents(CamPos) == CONTENT_SOLID) CamInitFlybyMode(CamTargEnt);
} else {
CamInitFlybyMode(CamTargEnt);
}
}
if (CamDrop < time) {
CamGoIdle();
}
};
// FIXED mode thinking routine
void() CamFixedThink =
{
local vector vec;
local entity ent;
local float cang;
local float a;
local float cscr; // count of targets on screen
local float maxscr; // minimum angle on screen
local float minscr; // maximum angle on screen
local float maxlo; // maximum angle of lowers
local float minhi; // minimum angle of highers
local vector scrv; // onscreen origin sum
local vector hiv; // lower optimum
local vector lov; // higher optimum
local float c;
cang = self.v_angle_y;
cscr = 0;
maxscr = -45;
minscr = 45;
maxlo = -181;
minhi = 181;
scrv = '0 0 0';
c = 0;
ent = CamCycle(world);
while (ent != world) {
if (ent.deadflag == DEAD_NO) {
if (CamVisible(ent.origin)) {
// Possible target is visible
// Look if it is "on screen"
c = c + 1;
vec = vectoangles(ent.origin - self.origin);
a = vec_y - cang;
while (a > 180) a = a - 360;
while (a < -180) a = a + 360;
if (fabs(a)<45) {
// entity is "on screen"
cscr = cscr + 1;
scrv = scrv + ent.origin;
if (a < minscr) minscr = a;
if (a > maxscr) maxscr = a;
} else {
if (a > 0) {
if (a < minhi) {
minhi = a;
hiv = ent.origin;
}
} else {
if (a > maxlo) {
maxlo = a;
lov = ent.origin;
}
}
}
}
}
ent = CamCycle(ent);
}
if (c > 0) {
if (c > 1) CamNextThink = time + 3;
if (cscr < c) {
if ((cscr == 0) || ((maxscr - maxlo) <= 90) || ((minhi - minscr) <= 90)) {
cscr = cscr + 1;
if ((maxscr - maxlo) > (minhi - minscr)) {
scrv = scrv + hiv;
} else {
scrv = scrv + lov;
}
}
}
scrv_x = scrv_x / cscr;
scrv_y = scrv_y / cscr;
scrv_z = scrv_z / cscr;
CamTarget = scrv;
}
CamPos = self.origin;
if ((CamNextThink < time) || (CamDrop < time)) {
CamGoIdle();
}
};
void(entity ent,entity que) CamCopyBody =
{
if (ent == CamTargEnt) {
CamTargEnt = que;
if (CamState != CAM_DEATH) {
CamGoDeath();
CamDrop = time + 5;
}
} else if (que == CamTargEnt) {
CamTargEnt = CamClient;
}
};
// DEATH mode think
void() CamDeathThink =
{
local float f;
if (CamDrop < time) {
CamGoIdle();
return;
}
if (CamTargEnt != CamClient) {
f = vlen(CamClient.origin - CamPos);
if ((f>1) || (CamAngV != '0 0 0')) {
f = time + 0.5;
if (CamNextThink < f) {
CamNextThink = f;
}
}
}
if (time > CamNextThink) {
CamGoIdle();
} else {
if (CamTargEnt != CamClient) {
CamTarget = CamTargEnt.origin;
}
}
if (CamTargEnt != CamClient) {
if (!CamVisible(CamTarget)){
CamInitFlybyMode(CamTargEnt);
CamState = CAM_DEATH;
CamNextThink = time + 2;
if (!CamVisible(CamTarget)){
if (CamTargEnt.velocity == '0 0 0'){
CamGoIdle();
}
}
}
if (CamTargEnt.velocity != '0 0 0') {
CamNextThink = time + 2;
}
}
if (vlen(CamPos - CamTarget)>60) {
CamPos = CamPos - CamTarget;
CamPos = normalize(CamPos);
CamPos = 59 * CamPos + CamTarget;
}
};
// Main camera thinking routine
// Called every frame
void() CamThink =
{
// Update visible values (health, armor, ...)
CamUpdValues();
self.velocity = '0 0 0';
// Status depending handling
if (CamState == CAM_IDLE) {
CamIdleThink();
CamUpdatePos(1,50);
} else if (CamState == CAM_FLYBY) {
CamFlyByThink();
CamUpdatePos(0,500);
} else if (CamState == CAM_FOLLOW) {
CamFollowThink();
CamUpdatePos(800,1000);
} else if (CamState == CAM_FIXED) {
CamFixedThink();
CamUpdatePos(0,70);
} else if (CamState == CAM_DEATH) {
CamDeathThink();
CamUpdatePos(100,150);
// } else if (CamState == CAM_HAND) { -- nothing to do
// } else if (CamState == CAM_FREE) { -- nothing to do
// } else if (CamState == CAM_NOCLIP) { -- nothing to do
// } else if (CamState == ...
}
// Impulse handling (standard is not active)
CamImpulses();
// Update time
CamLastFrameTime = time;
};
// CamClient initialization
void() CamClientInit =
{
local entity ent;
self.classname = "CameraClient";
setmodel (self, string_null);
self.weaponmodel = string_null;
setsize (self, '0 0 0', '0 0 0');
self.velocity = '0 0 0';
self.view_ofs = '0 0 0';
self.movetype = MOVETYPE_NONE;
self.solid = SOLID_NOT;
self.takedamage = DAMAGE_NO;
self.fixangle = TRUE;
self.nextthink = -1;
self.colormap = 0;
CamClient = self;
CamPos = self.origin;
makevectors(self.v_angle);
CamTarget = CamPos + 100 * v_forward;
CamTargEnt = CamClient;
CamLastTarg = world;
CamMsgs = TRUE;
CamAngV = '0 0 0';
CamNextThink = time;
CamForceTarget = time;
CamLastFrameTime = time;
// now reset all saved positions
ent = find(world,classname,"CamSavedPos");
while(ent!=world) {
ent.v_angle = self.v_angle;
ent.angles = self.angles;
setorigin(ent,self.origin);
ent = find(ent,classname,"CamSavedPos");
}
CamGoIdle();
bprint("Camera running");
};
// Main initialization
void() CamSpawn =
{
local float i;
local entity ent;
// initialize camera
CamClient = world;
// init saved positions
i=10;
do {
ent = spawn();
ent.classname = "CamSavedPos";
i = i - 1;
} while(i>0);
};